package com.fs.controller.v2;

import com.fs.realm.UserContext;
import com.fs.schedule.ScheduleTool;
import com.fs.controller.vo.door.RespOpenDoor;
import com.fs.global.init.RoleName;
import com.fs.service.*;
import com.fs.service.bo.cleaner.BoCleaner;
import com.fs.service.bo.cleaner.BoQueryParam;
import com.fs.service.bo.customer.BoCustomer;
import com.fs.service.bo.device.BoSwitch;
import com.fs.service.bo.purchase.BoPurchaseWithRoom;
import com.fs.service.bo.purchase.Status;
import com.fs.service.bo.room.BoRoom;
import com.fs.utils.Utils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Api(tags = "扫码开门", description = "小程序用户使用")
@Log4j2
@RestController
@RequestMapping("/v2/door")
@RequiresRoles(RoleName.CUSTOMER)
@Validated
public class DoorController {
    final PurchaseService purchaseService;
    final CustomerService customerService;
    final ScheduleTool scheduledTask;
    final DoorService doorService;
    final FriendService friendService;
    final RoomService roomService;
    final DeviceOperationService deviceOperation;
    final CleanerService cleanerService;

    public DoorController(PurchaseService purchaseService, CustomerService customerService,
                          ScheduleTool scheduledTask, DoorService doorService, FriendService friendService, RoomService roomService, DeviceOperationService deviceOperation, CleanerService cleanerService) {
        this.purchaseService = purchaseService;
        this.customerService = customerService;
        this.scheduledTask = scheduledTask;
        this.doorService = doorService;
        this.friendService = friendService;
        this.roomService = roomService;
        this.deviceOperation = deviceOperation;
        this.cleanerService = cleanerService;
    }

    @ApiOperation("扫码开门")
    @PostMapping("/{doorId}/open")
    public RespOpenDoor customerOpenDoor(@PathVariable("doorId") int doorId) {
        List<BoRoom> rooms = doorService.findRooms(doorId);
        List<Integer> roomIds = rooms.stream().map(BoRoom::getId).collect(Collectors.toList());
        int customerId = UserContext.getPrinciple();
        //查找用户本人的订单
        List<BoPurchaseWithRoom> purchases = purchaseService.getPurchaseOfRoomsOfCustomerOfPayedOfToday(roomIds,
                Collections.singletonList(customerId));
        if (purchases.size() == 0) {
            //查找用户作为被邀请者的订单
            BoCustomer friendCustomer = customerService.findById(customerId);
            List<BoCustomer> customers = friendService.findCustomerByFriendPhone(friendCustomer.getPhone());
            List<Integer> cusIds = customers.stream().map(BoCustomer::getId).collect(Collectors.toList());
            purchases = purchaseService.getPurchaseOfRoomsOfCustomerOfPayedOfToday(roomIds, cusIds);
            if (purchases.size() == 0) {
                return new RespOpenDoor().setCode(RespOpenDoor.Code.OrderNotFound).setDescribe("没有找到客户及其朋友在今天的订单");
            }
        }

        LocalDateTime now = LocalDateTime.now();
        purchases = purchases.stream().filter(p -> p.getBeginTime().isBefore(now) && p.getEndTime().isAfter(now))
                .collect(Collectors.toList());

        if (purchases.size() > 1) {
            log.warn("顾客在交叉时间内定了多个房间或者顾客有共同朋友?,客户id:" + customerId);
        }
        if (purchases.size() == 0) {
            return new RespOpenDoor().setCode(RespOpenDoor.Code.NotTimeForOpen).setDescribe("不在预定时段内");
        }

        //开门
        try {
            deviceOperation.openDoor(doorId);
        } catch (Exception e) {
            throw new DeviceControlException("开门异常");
        }
        //如果rooms个数等于>1,说明是公共门,不必执行下面的逻辑, rooms等于1, 则说明顾客扫的这个门是房间门
        if (rooms.size() == 1) {
            if (purchases.size() > 1) {
                return new RespOpenDoor().setCode(RespOpenDoor.Code.BusinessError).setDescribe("订单异常!请联系管理员");
            }

            BoPurchaseWithRoom boPurchase = purchases.get(0);
            BoRoom room = rooms.get(0);
            Assert.isTrue(boPurchase.getRoom().getId().equals(room.getId()), "roomId不一致,请检查数据!");

            if (boPurchase.getState() == Status.ToBeUsed) {
                //通电
                List<Integer> switchIds = roomService.findSwitchIds(room.getId());
                try {
                    deviceOperation.openSwitches(switchIds);
                } catch (Exception e) {
                    throw new DeviceControlException("启动空开异常");
                }

                //客户初次开门,创建保洁通知任务
                LocalDateTime ldt = boPurchase.getEndTime().minusMinutes(20);
                Date notifyDate = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
                String cleanTime = Utils.localDateTimeToString(boPurchase.getEndTime());
                List<BoCleaner> cleaners = cleanerService.getCleaners(
                        new BoQueryParam().setShopId(room.getShop().getId()));
                List<String> phoneList = cleaners.stream().map(BoCleaner::getPhone).collect(Collectors.toList());

                scheduledTask.addNotifyTask(new ScheduleTool.NotifyCleanTask(notifyDate, room.getName(), cleanTime, phoneList));

                //客户初次开门,创建关闭电源任务
                Date cutPowerDate = Date.from(boPurchase.getEndTime().atZone(ZoneId.systemDefault()).toInstant());
                scheduledTask.addCutPowerTask(new ScheduleTool.CutPowerTask(cutPowerDate, switchIds));

                //更新订单状态为已使用
                purchaseService.setPurchaseUsed(boPurchase.getId());
            }
        }

        return new RespOpenDoor().setCode(RespOpenDoor.Code.OpenSuccess).setDescribe("开门成功");
    }
}
